package com.wxxymaker.service;

import com.blade.ioc.annotation.Bean;
import com.blade.ioc.annotation.Inject;
import com.blade.kit.UUID;
import com.wxxymaker.model.dao.ArtImageDao;
import com.wxxymaker.model.dao.ArticleDao;
import com.wxxymaker.model.entity.Article;
import com.wxxymaker.utils.Const;
import com.wxxymaker.utils.FileUtils;
import com.wxxymaker.utils.SimpleCache;
import io.github.biezhi.anima.Anima;
import io.github.biezhi.anima.core.AnimaQuery;
import io.github.biezhi.anima.page.Page;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: Soft
 * @Date: 2018/6/30 0:42
 * @Desc:
 */
@Bean
public class ArticleService {
    @Inject
    private ArticleDao dao;

    @Inject
    private ArtImageDao imageDao;

    public void addLike(int id) {
        dao.addLike(id);
    }

    public void addView(int id) {
        dao.addView(id);
    }

    public Article add(Article article) {
        if (saveToHtmlAndDealPhoto(article)) {
            article.setTime(new Date());
            Integer key = article.save().asInt();
            article.setId(key);
        }
        return article;
    }

    public Article delete(int id) {
        Article delete = dao.delete(id);
        if (delete != null) { // 删除文章同时删除图片等文件
            FileUtils.deleteByWebPath(delete.getPath());
            if (delete.getType().equals(Article.Type.RESULT)) {
                FileUtils.deleteByWebPath(delete.getPhoto());
            }
            imageDao.get(delete.getFlagKey()).forEach(FileUtils::deleteByWebPath);
            imageDao.clear(delete.getFlagKey()); // 删除数据库中图片地址
        }
        return delete;
    }

    public boolean change(Article article) {
        String photo = Anima.select().from(Article.class).byId(article.getId()).getPhoto();
        if (photo != null && !"".equals(photo)) {
            String filename = photo.substring(photo.lastIndexOf("/") + 1);
            if (article.getPhoto() == null || // 当文件改变了删除
                    (article.getPhoto() != null && !article.getPhoto().contains(filename))) {
                FileUtils.deleteByWebPath(photo);
            }
            if (!Article.Type.RESULT.equals(article.getType()))
                article.setPhoto("");
        }
        return saveToHtmlAndDealPhoto(article) && dao.change(article) > 0;
    }

    public Article findOne(int id) {
        return dao.findOne(id);
    }

    public Page<Article> page(int pageNo) {
        return dao.page(pageNo, Const.shortPageSize, null);
    }

    public Page<Article> page(int pageNo, Map<String, Object> query) {
        return dao.page(pageNo, Const.shortPageSize, query);
    }

    public Page<Article> page(int pageNo, int size, Map<String, Object> query) {
        return dao.page(pageNo, size, query);
    }

    public Page<Article> like(String title) {
        return dao.titleLike(title);
    }

    /**
     * 计数 条件为类型和状态
     * @param type   类型
     * @param status 状态
     * @return 总数
     */
    public long count(String type, Integer status) {
        AnimaQuery<Article> from = Anima.select().from(Article.class);
        if (type != null && !"".equals(type)) {
            from.where(Article::getType, type);
        }

        if (status != null && status > -1) {
            from.where(Article::getStatus, status);
        }

        return from.count();
    }

    /**
     * 将文章内容保存到html文档，同时设置文档的路径，根据类型保存不同的文件夹中
     * 同时处理图片路径问题
     * @param article 文章实例
     * @return true or false
     */
    private boolean saveToHtmlAndDealPhoto(Article article) {
        if (null != article) {
            String photo = article.getPhoto();
            if (null != photo && !"".equals(photo) && photo.contains("temp")) { // 图片存在且在临时文件夹中 则移动
                String photoName = photo.substring(photo.lastIndexOf("/") + 1);
                article.setPhoto(FileUtils.tempMvToUpload("images", photoName));
            }

            if (null != article.getPath()) { // 文章文件存在则删除
                FileUtils.deleteByWebPath(article.getPath());
            }
            String content = article.getContent();
            if (null != content) {
                String flagKey = article.getFlagKey();
                List<String> images = this.getImages(content);
                List<String> urls;
                if (article.getId() != null && article.getId() > 0) { // 修改时
                    urls = imageDao.get(flagKey);
                } else {
                    /*
                    将文章无关的图片从本地清除
                    在上传文件时将图片路径放到缓存中
                     */
                    Map<String, List<String>> temps = ((Map<String, List<String>>)
                            SimpleCache.get(Const.tempImgKey));
                    urls = temps.get(flagKey);
                    temps.remove(flagKey); // 在缓存中删除本次文章的图片操作集合
                }
                if (urls != null) {
                    urls.stream() // 将于文章无关的图片从本地删除
                            .filter(u->!images.contains(u))
                            .forEach(FileUtils::deleteByWebPath);
                }

                imageDao.set(flagKey, images);  // 保存存在的图片到数据库

                String webPath = FileUtils.saveToUpload(("<meta charset='utf-8'>\r\n" + content).getBytes(),
                        "article_" + article.getType(), UUID.captchaChar(10) + ".html");
                article.setPath(webPath);
                article.setContent(null); // 清空 省内存
                return true;
            }
        }
        return false;
    }

    /**
     * 从html文档中获取所有图片的地址
     * @param html 文档
     * @return 图片地址列表
     */
    private List<String> getImages(String html) {
        List<String> urls = new ArrayList<>();

        Pattern imgPattern = Pattern.compile("<\\s*img\\s+(.*?)\\s*>");
        Pattern srcPattern = Pattern.compile("src=\"(.*?)\"");

        Matcher imgTag = imgPattern.matcher(html);
        while (imgTag.find()) {
            String  img = imgTag.group();
            Matcher src = srcPattern.matcher(img);
            if (src.find()) {
                urls.add(src.group().replaceAll("(^src=|\")", ""));
            }
        }
        return urls;
    }
}
